 
  

 






<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do?Id=163 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
<head>
 <title>
  Java Practices -> Filter table rows
 </title>
 <link rel="stylesheet" type="text/css" href="../stylesheet8.css" media="all">
 
 <link rel="shortcut icon" href='../images/favicon.ico' type="image/vnd.microsoft.icon">
 <meta name="description" content="Concise presentations of java programming practices, tasks, and conventions, amply illustrated with syntax highlighted code examples.">
 
 <meta name='keywords' content='JTable,JTree,QuoteFilter,QuoteFilterFactory,template,filter,swing,table,java,java programming,java practices,java idiom,java style,java design patterns,java coding conventions,'>
 
 
</head>
 
<body>


<div class='menu-bar'>
 
  <a href='../home/HomeAction.html' title='Table of Contents'>Home</a> |
  <a href='../vote/VoteSummaryAction-2.html' title='View Poll Results'>Poll</a> |
   
  <A href='../feedback/FeedbackAction451f-2.html?Operation=Show' title='Send Your Feedback'>Wiki</a> |
  <b><a href='../source/SourceAction-2.html' title='Grab Source Code'>Source Code</a></b><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |

  <a href='http://www.web4j.com/Java_Web_Application_Framework_Overview.jsp?From=1' title='Free Download - Java Web Application Framework'><b>WEB4J</b></a> |
  
  <a href='http://www.date4j.net/' title='Replacement for java.util.Date'><b>DATE4J</b></a> |

   <a href='../references/ReferencesAction-2.html' title='References'>Links</a>
   
  <form action='http://www.javapractices.com/search/SearchAction.do' method='get' class='search-form'>
   <input type='text' name='SearchTerms' value="" size=12 maxlength=50 class='search'>
   <input type='submit' value="Search">
  </form>
 
</div>

<P>



  

 






<p class="display-messages">

 

 

</p>


<div class="main-layout">
 
   

 




<div class='page-title'>Filter table rows</div>

<div class='main-body'>
 
<br>Filtering table rows according to some criterion is a common requirement
in Swing applications. JSE 6 has added a filter and sort mechanism to 
<tt><a href="http://java.sun.com/javase/6/docs/api/javax/swing/JTable.html">JTable</a></tt>, using 
<tt><a href="http://java.sun.com/javase/6/docs/api/javax/swing/RowSorter.html">RowSorter</a></tt>.


<p>The following example is for JSE 1.5. 
This example uses <tt>Quote</tt> objects, which are data-centric objects
containing information regarding the current price of a stock.
<p><tt>QuoteFilter</tt> is an abstract base class (sometimes called an
"ABC") which :
<ul>
<li>
defines <tt>isAcceptable</tt>, which must be implemented by concrete subclasses
(these represent specific filters)</li>

<li>
defines <tt>sift</tt>, a template method which calls <tt>isAcceptable</tt>,
and which applies a particular filter to a given <tt>Collection</tt> of
<tt>Quote</tt> objects</li>

<li>
does not have knowledge of any GUI elements</li>
</ul>
<br>
<PRE>

<span class='keyword'>package</span> hirondelle.stocks.table;

<span class='keyword'>import</span> hirondelle.stocks.quotes.Quote;
<span class='keyword'>import</span> java.util.*;

<span class='comment'>/**
* Allows collections of {@link Quote} objects 
* to be filtered according to a criterion defined by implementors.
*/</span>
<span class='keyword'>public</span> <span class='keyword'>abstract</span> <span class='keyword'>class</span> QuoteFilter {
  
  <span class='comment'>/**
  * Defines the criteria by which &lt;tt&gt;aQuote&lt;/tt&gt; is accepted or rejected 
  * by this filter.
  */</span>
  <span class='keyword'>abstract</span> <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable(Quote aQuote);
  
  <span class='comment'>/**
  * Return a &lt;tt&gt;List&lt;/tt&gt; which has the same 
  * iteration order as &lt;tt&gt;aQuotes&lt;/tt&gt;, but which includes only those elements 
  * which satisfy {@link #isAcceptable}.
  */</span>
  <span class='keyword'>public</span> <span class='keyword'>final</span> List&lt;Quote&gt; sift(Collection&lt;Quote&gt; aQuotes ){
    <span class='comment'>/*
    * This is an example of a template method : the general outline is
    * defined here in this abstract base class, but the implementation of 
    * specific steps (in this case the method isAcceptable) is left to 
    * concrete subclasses.
    *
    * Note as well that this method is final, so that no subclass can override this 
    * implementation.
    */</span>
    List&lt;Quote&gt; result = <span class='keyword'>new</span> ArrayList&lt;Quote&gt;();
    <span class='keyword'>for</span>(Quote quote : aQuotes){
      <span class='keyword'>if</span> ( isAcceptable(quote) ) {
        result.add( quote );
      }
    }
    <span class='keyword'>return</span> result;
  }
}
 
</PRE>
<br>
<br>The <tt>QuoteFilterFactory</tt> class
<ul>
<li>
defines all concrete implementations of <tt>QuoteFilter</tt> (using static
private classes)</li>

<li>
provides a graphical interface for user selection of these filter implementations
(using the <tt>JTree</tt> called <tt>fFilterSelector</tt>)</li>
</ul>
<tt>QuoteFilterFactory</tt> uses the idea of attaching a "user object"
to each node of a <tt>JTree</tt>. These user objects are the <tt>QuoteFilter</tt>
implementations. When the user clicks on a new node, listeners attached
to <tt>QuoteFilterFactory</tt> are informed of the change, and use <tt>getSelectedFilter</tt>
to fetch the corresponding filter. (See <tt>updateFilterAndBroadcast</tt>.)
<br>
<PRE>

<span class='keyword'>package</span> hirondelle.stocks.table;

<span class='keyword'>import</span> java.util.logging.*;
<span class='keyword'>import</span> java.util.*;

<span class='keyword'>import</span> javax.swing.*;
<span class='keyword'>import</span> javax.swing.event.*;
<span class='keyword'>import</span> javax.swing.tree.*;
<span class='keyword'>import</span> java.awt.*;

<span class='keyword'>import</span> hirondelle.stocks.quotes.Stock;
<span class='keyword'>import</span> hirondelle.stocks.quotes.Quote;
<span class='keyword'>import</span> hirondelle.stocks.quotes.Exchange;
<span class='keyword'>import</span> hirondelle.stocks.util.Consts;
<span class='keyword'>import</span> hirondelle.stocks.portfolio.CurrentPortfolio;
<span class='keyword'>import</span> hirondelle.stocks.util.Util;

<span class='comment'>/**
* Graphical component which allows the end user to select a 
* {@link QuoteFilter}, and informs its listeners of changes 
* to this selection.
*
* &lt;P&gt;When informed of selection changes, listeners call {@link #getSelectedFilter}
* and use the returned &lt;tt&gt;QuoteFilter&lt;/tt&gt; to alter their display to reflect 
* only those items in the {@link CurrentPortfolio} which satisfy certain criteria.
*
* &lt;P&gt;The initial state of this class has no item selected, and 
* {@link #getSelectedFilter} returns a &lt;tt&gt;QuoteFilter&lt;/tt&gt;
* which accepts all {@link Quote} objects. 
* When the &lt;tt&gt;CurrentPortfolio&lt;/tt&gt; is changed, this initial state is recreated. 
*
* &lt;p&gt;Property Listeners are notified only when a selection is made actively by the
* user, and only if the selection is different from the previous selection.
*/</span>
<span class='keyword'>public</span> <span class='keyword'>final</span> <span class='keyword'>class</span> QuoteFilterFactory <span class='keyword'>extends</span> JScrollPane <span class='keyword'>implements</span> Observer {

  <span class='comment'>/**
  * Constructor.
  *  
  * @param aCurrentPortfolio is observed by this class, since the list of 
  * possible filters displayed by this class depends on its content.
  */</span>
  <span class='keyword'>public</span> QuoteFilterFactory (CurrentPortfolio aCurrentPortfolio){
    fCurrentPortfolio = aCurrentPortfolio;
    fCurrentPortfolio.addObserver(<span class='keyword'>this</span>);
    fSelectedFilter = NO_SELECTION_FILTER;
    initGui();
  }
  
  <span class='comment'>/**
  * Return the &lt;tt&gt;QuoteFilter&lt;/tt&gt; 
  * attached to the currently selected item. If no selection is present, 
  * then return a &lt;tt&gt;QuoteFilter&lt;/tt&gt; which accepts all {@link Quote} objects.
  */</span>
  <span class='keyword'>public</span> QuoteFilter getSelectedFilter(){
    assert fSelectedFilter != <span class='keyword'>null</span> : <span class='literal'>"Filter has null value."</span>;
    <span class='keyword'>return</span> fSelectedFilter;
  }

  <span class='comment'>/**
  * Update this component's GUI in response to changes in the 
  * {@link CurrentPortfolio} passed to the constructor.
  */</span>
  <span class='keyword'>public</span> <span class='keyword'>void</span> update(Observable aObservable, Object aData) {
    fSelectedFilter = NO_SELECTION_FILTER;
    synchFilterTreeWithCurrentPortfolio();
  } 
  
  <span class='comment'>/**
  * Property name passed to listeners during &lt;tt&gt;PropertyChangeEvent&lt;/tt&gt;.
  */</span>
  <span class='keyword'>public</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String SELECTED_FILTER = <span class='literal'>"SelectedFilter"</span>;
  
  <span class='comment'>// PRIVATE //
</span>
  <span class='keyword'>private</span> CurrentPortfolio fCurrentPortfolio;
  <span class='keyword'>private</span> DefaultTreeModel fFilterTreeModel;
  
  <span class='comment'>/**
  * The GUI element which allows the user to select a particular filter.
  */</span>
  <span class='keyword'>private</span> JTree fFilterSelector;
  
  <span class='comment'>/**
  * The {@link QuoteFilter} corresponding to the user's 
  * current non-null selection.
  */</span>
  <span class='keyword'>private</span> QuoteFilter fSelectedFilter;
  
  <span class='comment'>/**
  * The {@link QuoteFilter} corresponding to the absence of 
  * any user selection.
  */</span>
  <span class='keyword'>private</span> QuoteFilter NO_SELECTION_FILTER = <span class='keyword'>new</span> QuoteFilterAcceptAll(Consts.EMPTY_STRING);

  <span class='comment'>/*
  * These Strings appear as node names in fFilterSelector.
  */</span>
  
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String FILTER_BY = <span class='literal'>"Filter By"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String EXCHANGE = <span class='literal'>"Exchange"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String TODAYS_CHANGE = <span class='literal'>"Today's Change"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String GAINERS = <span class='literal'>"Gainers"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String LOSERS = <span class='literal'>"Losers"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String TICKER_TYPE = <span class='literal'>"Ticker Type"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String INDEX = <span class='literal'>"Index"</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> String NON_INDEX = <span class='literal'>"Non-Index"</span>;
  
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> Logger fLogger = Util.getLogger(QuoteFilterFactory.<span class='keyword'>class</span>);  
  
  <span class='comment'>/**
  * Build a tree corresponding to the contents of the {@link CurrentPortfolio}, 
  * and attach a corresponding {@link QuoteFilter} to 
  * every tree node.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>void</span> initGui(){
    initFilterTreeModel();
    initFilterTree();
    synchFilterTreeWithCurrentPortfolio();
    setViewportView( fFilterSelector );
    setPreferredSize( <span class='keyword'>new</span> Dimension(<span class='literal'>160</span>,<span class='literal'>240</span>) );
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> initFilterTreeModel(){
    DefaultMutableTreeNode exchange =  <span class='keyword'>new</span> DefaultMutableTreeNode( 
      <span class='keyword'>new</span> QuoteFilterAcceptAll(EXCHANGE) 
    );
    <span class='comment'>//children of exchange depend on current portfolio, and are added a bit later
</span>    
    <span class='comment'>//note how user objects are critical here, and must be attached to ALL nodes.
</span>    DefaultMutableTreeNode todaysChange =  <span class='keyword'>new</span> DefaultMutableTreeNode(
      <span class='keyword'>new</span> QuoteFilterAcceptAll(TODAYS_CHANGE) 
    );
    todaysChange.add( <span class='keyword'>new</span> DefaultMutableTreeNode(<span class='keyword'>new</span> QuoteFilterGainers()) );
    todaysChange.add( <span class='keyword'>new</span> DefaultMutableTreeNode(<span class='keyword'>new</span> QuoteFilterLosers()) );

    DefaultMutableTreeNode tickerType =  <span class='keyword'>new</span> DefaultMutableTreeNode(
      <span class='keyword'>new</span> QuoteFilterAcceptAll(TICKER_TYPE) 
    );
    tickerType.add( <span class='keyword'>new</span> DefaultMutableTreeNode(<span class='keyword'>new</span> QuoteFilterIndex()) );
    tickerType.add( <span class='keyword'>new</span> DefaultMutableTreeNode(<span class='keyword'>new</span> QuoteFilterNonIndex()) );
    
    DefaultMutableTreeNode filterBy = <span class='keyword'>new</span> DefaultMutableTreeNode(
      <span class='keyword'>new</span> QuoteFilterAcceptAll(FILTER_BY) 
    );
    filterBy.add(exchange);
    filterBy.add(todaysChange);
    filterBy.add(tickerType);
    
    fFilterTreeModel = <span class='keyword'>new</span> DefaultTreeModel(filterBy);
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> initFilterTree(){
    fFilterSelector = <span class='keyword'>new</span> JTree(fFilterTreeModel);
    fFilterSelector.setRootVisible(<span class='keyword'>true</span>); <span class='comment'>//recommended "false" by L&F guidelines
</span>    fFilterSelector.setShowsRootHandles(<span class='keyword'>true</span>); <span class='comment'>//recommended by L&F guidelines
</span>    fFilterSelector.setEditable(<span class='keyword'>false</span>); 
    fFilterSelector.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION
    );
    
    <span class='comment'>//Note that using a local class hides the fact that this class 
</span>    <span class='comment'>//listens to a JTree; the public valueChanged event is not exposed in the 
</span>    <span class='comment'>//public API of this class, since that method is of no interest to the caller; 
</span>    <span class='comment'>//it is an implementation detail.
</span>    fFilterSelector.addTreeSelectionListener(<span class='keyword'>new</span> TreeSelectionListener() {
      <span class='keyword'>public</span> <span class='keyword'>void</span> valueChanged(TreeSelectionEvent e) {
        updateFilterAndBroadcast();      
      }
    });
  }
  
  <span class='comment'>/**
  * For each Exchange present in the {@link CurrentPortfolio}, add a single
  * node to the filter tree (under the Exchange branch), assign a 
  * {@link QuoteFilterExchange} as the user object, and ensure no item is selected.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>void</span> synchFilterTreeWithCurrentPortfolio() {
    DefaultMutableTreeNode filterBy = 
      (DefaultMutableTreeNode)fFilterTreeModel.getRoot()
    ;
    <span class='comment'>//DEPENDENCY: the exchange node is the *first* item:
</span>    DefaultMutableTreeNode exchangesNode = 
      (DefaultMutableTreeNode)filterBy.getFirstChild()
    ;
    exchangesNode.removeAllChildren();
    
    Set&lt;Exchange&gt; exchanges = <span class='keyword'>new</span> LinkedHashSet&lt;Exchange&gt;();
    <span class='keyword'>for</span>(Stock stock: fCurrentPortfolio.getStocks()){
      Exchange exchange = stock.getExchange();
      <span class='keyword'>if</span> ( ! exchanges.contains(exchange) ) {
        exchanges.add(exchange);
        exchangesNode.add(<span class='keyword'>new</span> DefaultMutableTreeNode(<span class='keyword'>new</span> QuoteFilterExchange(exchange))); 
      }
    }
    fFilterTreeModel.reload(); <span class='comment'>//fires a selection event, but it is suppressed
</span>  }

  <span class='comment'>/**
  * Update listeners in response to a new filter selection in the GUI. 
  *
  * &lt;P&gt;If a new {@link CurrentPortfolio} is selected, then 
  * the tree will have no selection, and this method will do nothing.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>void</span> updateFilterAndBroadcast() {
    <span class='keyword'>if</span> ( hasNoSelection() ) <span class='keyword'>return</span>;
    QuoteFilter newSelectedFilter = parseSelectedFilter();
    assert newSelectedFilter != <span class='keyword'>null</span> : <span class='literal'>"New filter is unexpectedly null."</span>;
    assert newSelectedFilter != NO_SELECTION_FILTER : <span class='literal'>"New Filter is unexpected value."</span>;
    <span class='keyword'>if</span> ( fSelectedFilter == newSelectedFilter ) {
      fLogger.fine(<span class='literal'>"No broadcast: user selection does not have a new filter"</span>);
    }
    <span class='keyword'>else</span> {
      fLogger.fine(<span class='literal'>"New filter being broadcast: "</span> + newSelectedFilter);
      QuoteFilter oldSelectedFilter = fSelectedFilter;
      fSelectedFilter = newSelectedFilter;
      firePropertyChange(SELECTED_FILTER, oldSelectedFilter, fSelectedFilter);
    }
  }

  <span class='comment'>/**
  * Return true only if the user has made no filter selection.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>boolean</span> hasNoSelection(){
    <span class='keyword'>return</span> (getSelectedNode() == <span class='keyword'>null</span>);
  }

  <span class='comment'>/**
  * Must call {@link #hasNoSelection} before invoking this method, to ensure that
  * a selection exists and is not null.
  */</span>
  <span class='keyword'>private</span> QuoteFilter parseSelectedFilter(){
    assert getSelectedNode() != <span class='keyword'>null</span> : <span class='literal'>"Selected Filter unexpectedly null."</span>;
    <span class='keyword'>return</span> (QuoteFilter)getSelectedNode().getUserObject();
  }
  
  <span class='comment'>/**
  * Return value is null if no selection is currently made.
  */</span>
  <span class='keyword'>private</span> DefaultMutableTreeNode getSelectedNode(){
    <span class='keyword'>return</span> (DefaultMutableTreeNode) fFilterSelector.getLastSelectedPathComponent();
  }

  <span class='comment'>/// All QuoteFilter implementations ///
</span>  
  <span class='comment'>/**
  * No {@link Quote} objects are rejected by this filter.
  *
  *&lt;P&gt; Since more than one tree node uses this filter, text is 
  * passed to the constructor to allows for customized display.
  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterAcceptAll <span class='keyword'>extends</span> QuoteFilter {
    QuoteFilterAcceptAll(String aText) {
      fText = aText;
    }
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> <span class='keyword'>true</span>;
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> fText;
    }
    <span class='keyword'>private</span> <span class='keyword'>final</span> String fText;
  }
  
  <span class='comment'>/**
  * {@link Quote} objects are accepted only if they are from a specific 
  * {@link Exchange}.
  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterExchange <span class='keyword'>extends</span> QuoteFilter {
    QuoteFilterExchange( Exchange aExchange ) {
      fTargetExchange = aExchange;
    }
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> aQuote.getStock().getExchange() == fTargetExchange;
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> fTargetExchange.toString();
    }
    <span class='keyword'>private</span> Exchange fTargetExchange;
  }
  
  <span class='comment'>/**
  * {@link Quote} objects are accepted only if todays price change is 
  * non-negative.
  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterGainers <span class='keyword'>extends</span> QuoteFilter {
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> aQuote.getChange().doubleValue() >= <span class='literal'>0.0</span>;
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> GAINERS;
    }
  }

  <span class='comment'>/** 
  * {@link Quote} objects are accepted only if todays price change is negative.
  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterLosers <span class='keyword'>extends</span> QuoteFilter {
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> aQuote.getChange().doubleValue() &lt; <span class='literal'>0.0</span>;
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> LOSERS;
    }
  }
  
  <span class='comment'>/** {@link Quote} objects are accepted only if it is an index.  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterIndex <span class='keyword'>extends</span> QuoteFilter {
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> aQuote.getStock().isIndex();
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> INDEX;
    }
  }

  <span class='comment'>/** {@link Quote} objects are accepted only if it is not an index.  */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> <span class='keyword'>class</span> QuoteFilterNonIndex <span class='keyword'>extends</span> QuoteFilter {
    <span class='keyword'>public</span> <span class='keyword'>boolean</span> isAcceptable( Quote aQuote ){
      <span class='keyword'>return</span> !aQuote.getStock().isIndex();
    }
    <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
      <span class='keyword'>return</span> NON_INDEX;
    }
  }
}
 
</PRE>
<br>
<br>
<br>

</div>




<div class='topic-section'>See Also :</div>
<div class='main-body'>
 
  
  <a href='TopicActiond357-2.html?Id=156'>Observers and listeners</a> <br>
 
  
  <a href='TopicActiond0e1-2.html?Id=162'>Sort table rows</a> <br>
 
</div>


<div class='topic-section'>Would you use this technique?</div>
<div class='main-body'>
  
  <form action="http://www.javapractices.com/vote/AddVoteAction.do" method='post'>
    Yes<input type='radio' name='Choice' value='Y' >
    &nbsp;&nbsp;No<input type='radio' name='Choice' value='N'>
    &nbsp;&nbsp;Undecided<input type='radio' name='Choice' value="?" >
    &nbsp;&nbsp;<input type=submit value="Vote" >
    <input type='hidden' name='Operation' value='Apply'>
    <input type='hidden' name='TopicId' value='163'>
  </form>
</div>

<div style='height:10.0em;'></div>

 
 
</div>

  

 





<div align='center' class='legalese'>  
&copy; 2011 Hirondelle Systems |
<a href='../source/SourceAction-2.html'><b>Source Code</b></a><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |
<a href="mailto:webmaster@javapractices.com">Contact</a> |
<a href="http://creativecommons.org/licenses/by-nc-sa/1.0/">License</a> |
<a href='../apps/cjp.rss'>RSS</a>
<!-- ukey="2AC36CD2" -->
<!-- ckey="16DF3D87" -->
<br>

 Individual code snippets can be used under this <a href='../LICENSE.txt'>BSD license</a> - Last updated on June 6, 2010.<br>
 Over 150,000 unique IPs last month - <span title='Java Practices 2.6.5, Mon May 16 00:00:00 EDT 2011'>Built with</span> <a href='http://www.web4j.com/'>WEB4J</a>.<br>
 - In Memoriam : Bill Dirani -
</div>

<script src="../../www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2633428-1";
urchinTracker();
</script>



</body>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do?Id=163 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
</html>
